﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Text;

public class HybridDependencyAnalyzer
{
    // PE文件结构常量
    private const ushort IMAGE_DOS_SIGNATURE = 0x5A4D;      // MZ
    private const uint IMAGE_NT_SIGNATURE = 0x00004550;    // PE00
    private const uint IMAGE_DIRECTORY_ENTRY_IMPORT = 1;

    [StructLayout(LayoutKind.Sequential)]
    private struct IMAGE_IMPORT_DESCRIPTOR
    {
        public uint OriginalFirstThunk;
        public uint TimeDateStamp;
        public uint ForwarderChain;
        public uint Name;
        public uint FirstThunk;
    }

    public AnalysisResult AnalyzeHybridDependencies(string dllPath)
    {
        var result = new AnalysisResult();
        try
        {
            if (!File.Exists(dllPath))
                throw new FileNotFoundException("文件不存在");

            result.ManagedDependencies = GetManagedDependencies(dllPath);
            result.NativeDependencies = GetNativeDependencies(dllPath);
        }
        catch (Exception ex)
        {
            result.ErrorMessage = ex.Message;
        }
        return result;
    }

    private List<AssemblyName> GetManagedDependencies(string dllPath)
    {
        var dependencies = new List<AssemblyName>();
        try
        {
            var assembly = Assembly.ReflectionOnlyLoadFrom(dllPath);
            foreach (var refAsm in assembly.GetReferencedAssemblies())
            {
                dependencies.Add(refAsm);
            }
        }
        catch (BadImageFormatException) { }
        return dependencies;
    }

    private List<string> GetNativeDependencies(string dllPath)
    {
        var dependencies = new List<string>();
        try
        {
            using (var fs = new FileStream(dllPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
            using (var reader = new BinaryReader(fs))
            {
                // 基础验证
                if (fs.Length < 0x40) return dependencies;
                if (SafeReadUInt16(reader) != IMAGE_DOS_SIGNATURE) return dependencies;

                // 定位PE头
                fs.Position = 0x3C;
                int peHeaderOffset = SafeReadInt32(reader);
                if (peHeaderOffset < 0x40 || peHeaderOffset > fs.Length - 4) return dependencies;

                // 验证PE签名
                fs.Position = peHeaderOffset;
                if (SafeReadUInt32(reader) != IMAGE_NT_SIGNATURE) return dependencies;

                // 解析COFF头
                fs.Position = peHeaderOffset + 4;
                ushort machine = SafeReadUInt16(reader);
                bool is64Bit = machine == 0x8664;

                // 跳过NumberOfSections和时间戳
                fs.Position += 12;

                // 获取可选头大小
                ushort optionalHeaderSize = SafeReadUInt16(reader);

                // 计算数据目录偏移
                int dataDirCount = 16;
                int optionalHeaderStart = peHeaderOffset + 24;
                int dataDirectoryOffset = optionalHeaderStart + (is64Bit ? 0x70 : 0x60);

                // 验证数据目录位置
                if (dataDirectoryOffset + dataDirCount * 8 > fs.Length)
                {
                    Console.WriteLine("数据目录超出文件范围");
                    return dependencies;
                }

                // 定位到导入表目录项
                fs.Position = dataDirectoryOffset + 8 * IMAGE_DIRECTORY_ENTRY_IMPORT;
                uint importRva = SafeReadUInt32(reader);
                uint importSize = SafeReadUInt32(reader);

                if (importRva == 0 || importSize == 0)
                {
                    Console.WriteLine("导入表为空");
                    return dependencies;
                }

                // 解析节表
                var sections = ReadSectionHeaders(reader, peHeaderOffset);
                long importOffset = RvaToOffset(importRva, sections);

                if (importOffset == -1)
                {
                    Console.WriteLine($"无法定位导入表偏移 (RVA: 0x{importRva:X8})");
                    return dependencies;
                }

                // 读取导入表
                fs.Position = importOffset;
                while (fs.Position <= fs.Length - 20) // 每个描述符20字节
                {
                    var descriptor = ReadStruct<IMAGE_IMPORT_DESCRIPTOR>(reader);
                    if (descriptor.Name == 0) break;

                    long nameOffset = RvaToOffset(descriptor.Name, sections);
                    if (nameOffset == -1) continue;

                    fs.Position = nameOffset;
                    string dllName = ReadNullTerminatedString(reader);
                    dependencies.Add(dllName);
                }
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine($"原生依赖分析错误: {ex.Message}");
        }
        return dependencies;
    }
    #region Helper Methods
    private ushort SafeReadUInt16(BinaryReader reader)
    {
        const int size = sizeof(ushort);
        if (reader.BaseStream.Position + size > reader.BaseStream.Length)
            throw new EndOfStreamException();
        return reader.ReadUInt16();
    }

    private int SafeReadInt32(BinaryReader reader)
    {
        const int size = sizeof(int);
        if (reader.BaseStream.Position + size > reader.BaseStream.Length)
            throw new EndOfStreamException();
        return reader.ReadInt32();
    }

    private uint SafeReadUInt32(BinaryReader reader)
    {
        const int size = sizeof(uint);
        if (reader.BaseStream.Position + size > reader.BaseStream.Length)
            throw new EndOfStreamException();
        return reader.ReadUInt32();
    }

    private T ReadStruct<T>(BinaryReader reader) where T : struct
    {
        int size = Marshal.SizeOf(typeof(T));
        byte[] buffer = SafeReadBytes(reader, size);
        GCHandle handle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
        try
        {
            return (T)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(T));
        }
        finally
        {
            handle.Free();
        }
    }

    private byte[] SafeReadBytes(BinaryReader reader, int count)
    {
        if (reader.BaseStream.Position + count > reader.BaseStream.Length)
            throw new EndOfStreamException();
        return reader.ReadBytes(count);
    }

    private string ReadNullTerminatedString(BinaryReader reader)
    {
        var bytes = new List<byte>();
        try
        {
            while (bytes.Count < 1024) // 防止无限循环
            {
                byte b = reader.ReadByte();
                if (b == 0) break;
                bytes.Add(b);
            }
        }
        catch (EndOfStreamException) { }
        return Encoding.ASCII.GetString(bytes.ToArray());
    }

    private List<SectionHeader> ReadSectionHeaders(BinaryReader reader, int peHeaderOffset)
    {
        var sections = new List<SectionHeader>();
        try
        {
            // 定位到节表
            reader.BaseStream.Position = peHeaderOffset + 6; // 跳过Signature和Machine
            ushort numSections = SafeReadUInt16(reader);
            reader.BaseStream.Position += 14; // 跳过TimeDateStamp等字段

            // 跳过可选头
            ushort optionalHeaderSize = SafeReadUInt16(reader);
            reader.BaseStream.Position += optionalHeaderSize;

            // 读取节表
            for (int i = 0; i < numSections; i++)
            {
                if (reader.BaseStream.Position + 40 > reader.BaseStream.Length)
                    break;

                sections.Add(new SectionHeader
                {
                    Name = Encoding.ASCII.GetString(SafeReadBytes(reader, 8)).TrimEnd('\0'),
                    VirtualAddress = SafeReadUInt32(reader),
                    SizeOfRawData = SafeReadUInt32(reader),
                    PointerToRawData = SafeReadUInt32(reader)
                });
                reader.BaseStream.Position += 20; // 跳过其他字段
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine($"节表解析错误: {ex.Message}");
        }
        return sections;
    }

    private long RvaToOffset(uint rva, List<SectionHeader> sections)
    {
        foreach (var section in sections)
        {
            if (rva >= section.VirtualAddress &&
                rva < section.VirtualAddress + section.SizeOfRawData)
            {
                return section.PointerToRawData + (rva - section.VirtualAddress);
            }
        }
        return -1;
    }
    #endregion

    private class SectionHeader
    {
        public string Name { get; set; }
        public uint VirtualAddress { get; set; }
        public uint SizeOfRawData { get; set; }
        public uint PointerToRawData { get; set; }
    }
}

public class AnalysisResult
{
    public List<AssemblyName> ManagedDependencies { get; set; } = new List<AssemblyName>();
    public List<string> NativeDependencies { get; set; } = new List<string>();
    public string ErrorMessage { get; set; }
}